package com.powernode.ssm.handler;

import com.powernode.ssm.exception.BusinessException;
import com.powernode.ssm.utils.ResponseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;

@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

    // ✅ 使用 SLF4J 记录日志（配合 logback.xml 或 application.yml 中的日志配置）
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * ✅ 处理参数校验异常（@Validated + @NotNull/@NotBlank 等注解，作用于对象字段）
     * 捕获 MethodArgumentNotValidException，通常是 @RequestBody 参数校验失败
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ResponseUtils<Void>> handleValidationException(MethodArgumentNotValidException ex) {
        // 提取字段错误信息，如 "name: 不能为空, age: 必须为正数"
        String errorMsg = ex.getBindingResult().getFieldErrors().stream()
                .map(error -> error.getField() + ": " + error.getDefaultMessage())
                .collect(Collectors.joining("; "));

        ResponseUtils<Void> response = new ResponseUtils<>(
                HttpStatus.BAD_REQUEST.value(), // 400
                "参数校验失败: " + errorMsg,
                null
        );

        logger.warn("参数校验异常: {}", errorMsg);
        return ResponseEntity.badRequest().body(response);
    }

    /**
     * ✅ 可选：处理简单参数校验异常（如 @RequestParam 上使用 @NotBlank，会抛出 ConstraintViolationException）
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<ResponseUtils<Void>> handleConstraintViolationException(ConstraintViolationException ex) {
        String errorMsg = ex.getConstraintViolations().stream()
                .map(v -> v.getPropertyPath() + ": " + v.getMessage())
                .collect(Collectors.joining("; "));

        ResponseUtils<Void> response = new ResponseUtils<>(
                HttpStatus.BAD_REQUEST.value(),
                "参数校验失败: " + errorMsg,
                null
        );

        logger.warn("请求参数校验异常: {}", errorMsg);
        return ResponseEntity.badRequest().body(response);
    }

    /**
     * ✅ 处理自定义业务异常（BusinessException）
     * 比如用户不存在、权限不足等逻辑异常，通常返回 4xx 状态码
     */
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ResponseUtils<Void>> handleBusinessException(BusinessException ex) {
        ResponseUtils<Void> response = new ResponseUtils<>(
                ex.getCode(), // 自定义业务错误码，比如 404、600 等
                ex.getMessage(),
                null
        );

        logger.warn("业务异常 [code={}]: {}", ex.getCode(), ex.getMessage());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
    }

    /**
     * ✅ 兜底全局异常处理：捕获所有未被处理的异常，避免暴露敏感信息
     * 返回 500 服务器错误，日志中打印完整异常堆栈
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ResponseUtils<Void>> handleException(Exception ex) {
        // 生产环境不要直接把 ex.getMessage() 返回给用户，这里可以返回友好提示
        String safeMsg = "服务器内部错误，请稍后再试";
        String debugMsg = ex.getMessage(); // 仅用于日志

        ResponseUtils<Void> response = new ResponseUtils<>(
                HttpStatus.INTERNAL_SERVER_ERROR.value(), // 500
                safeMsg,
                null
        );

        // 打印完整异常日志（包括堆栈）
        logger.error("全局兜底异常捕获: {}", debugMsg, ex);

        return ResponseEntity
                .status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(response);
    }
}